<template>
  <t-dialog
    :header="header"
    :visible.sync="visible"
    :onClose="closeDialog"
    :closeOnOverlayClick="false"
    @confirm="onSubmit"
    :confirmBtn="{
        content: loading?'提交中...':'确认',
        theme: 'primary',
        loading: loading,
      }"
    width="60%"
    top="5%"
  >
    <div style="height: 65vh;overflow: scroll">
      <t-form ref="form" :colon="true" :data="formData" labelWidth="100px" :rules="rules">
        <t-form-item label="角色名称" name="roleName">
          <t-input clearable v-model="formData.roleName" :maxlength="30" placeholder="请输入角色名称"></t-input>
        </t-form-item>
        <t-form-item label="权限字符" name="roleKey">
          <t-input clearable v-model="formData.roleKey" :maxlength="30" placeholder="请输入权限字符"></t-input>
          <template slot="label">
            <t-tooltip content="控制器中定义的权限字符，如：@PreAuthorize(`@ss.hasRole('admin')`)">
              <t-icon name="help-circle-filled"></t-icon>
            </t-tooltip>
            权限字符
          </template>
        </t-form-item>
        <t-form-item label="角色顺序" name="roleSort">
          <t-input-number clearable v-model="formData.roleSort" :min="0" placeholder="请输入"></t-input-number>
        </t-form-item>
        <t-form-item label="状态" name="status">
          <t-radio-group v-model="formData.status" :options="dict.type.sys_normal_disable">
            <!--          <t-radio value="1"> 正常</t-radio>-->
            <!--          <t-radio value="2"> 停用</t-radio>-->
          </t-radio-group>
        </t-form-item>
        <t-form-item label="子系统">
          <t-checkbox-group class="servicebox" @change="serviceChange" v-model="formData.serviceIds">
            <t-checkbox v-for="(item,index) in serviceList" :value="item.id" :key="index"
                        :label="item.serviceName"></t-checkbox>
          </t-checkbox-group>
        </t-form-item>
        <t-form-item label="菜单权限">
          <div class="menubox">
            <t-space :size="25">
              <t-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand">展开/折叠</t-checkbox>
              <t-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll">全选/全不选</t-checkbox>
              <t-checkbox v-model="menuCheckStrictly">父子联动</t-checkbox>
            </t-space>
            <t-tree
              class="tree-border"
              ref="tree"
              :data="menuOptions"
              valueMode="all"
              :keys="{value:'id'}"
              :expandAll="menuExpand"
              :check-strictly="!menuCheckStrictly"
              :expand-on-click-node="true"
              :allowFoldNodeOnFilter="menuExpand"
              checkable
              hover
            />
          </div>
        </t-form-item>
        <t-form-item label="备注" name="remark">
          <t-textarea
            v-model="formData.remark"
            placeholder="请输入内容"
          />
        </t-form-item>
      </t-form>
    </div>
  </t-dialog>
</template>

<script>
import {
  listRole,
  getRole,
  delRole,
  addRole,
  updateRole,
  dataScope,
  changeRoleStatus,
  sysServiceList,
  selectServiceListByRoleId
} from "@/api/system/role";
import {treeselect as menuTreeselect, roleMenuTreeselect} from "@/api/system/menu";

export default {
  name: "add-edit-role",
  dicts: ['sys_normal_disable'],
  components: {},
  props: ['header', 'roleId'],
  data() {
    return {
      allowFoldNodeOnFilter: false,
      visible: true,
      loading: false,
      formData: {
        roleName: "",
        status: "0",
        roleSort: 0,
        roleKey: "",
        remark: "",
        serviceIds: [],
        menuIds: [],
      },
      menuExpand: false,
      menuNodeAll: false,
      menuCheckStrictly: true,
      menuExpandedValue: [],
      menuOptions: [],
      serviceList: [],
      defaultProps: {
        children: "children",
        label: "label"
      },
      // 表单校验
      rules: {
        roleName: [
          {required: true, message: "角色名称不能为空"}
        ],
        roleKey: [
          {required: true, message: "权限字符不能为空"}
        ],
        roleSort: [
          {required: true, message: "角色顺序不能为空"}
        ],
        // serviceIds: [
        //   { required: true, message: "微服务不能为空" }
        // ]
      },
    }
  },
  watch: {
    roleId: {
      immediate: true,
      handler(val) {
        if (val) {
          this.getRole();
        }
      }
    }
  },
  created() {
    // this.getMenuTreeselect();
    this.getServiceList();
  },
  methods: {
    serviceMenuCheck(menuIds) {
      const array = []
      this.formData.serviceIds.forEach(val => {
        array.push(menuTreeselect({serviceId: val}))
      })
      const newMenuOptions = []
      Promise.all(array).then(response => {
        response.forEach(val => {
          if (val.data.length > 0) {
            newMenuOptions.push(...val.data);
          }
        });
        this.menuOptions = newMenuOptions;
        this.formData.menuIds = menuIds;
        // this.$nextTick(() => {
        //   this.setCheckedData(menuIds)
        // })
        this.setCheckedData(menuIds);
      }).catch((e) => {
        this.$message.error(e.toString());
      });
    },
    serviceChange() {
      if (this.roleId && this.roleId !== 0) {
        roleMenuTreeselect(this.roleId).then(response => {
          this.serviceMenuCheck(response.checkedKeys);
        }).catch((e) => {
          this.$message.error(e.toString());
        });
      } else {
        this.serviceMenuCheck([]);
      }
    },
    /** 查询菜单树结构 */
    getMenuTreeselect() {
      menuTreeselect().then(response => {
        this.menuOptions = response.data;
      }).catch((e) => {
        this.$message.error(e.toString());
      });
    },
    // 获取微服务列表
    getServiceList() {
      sysServiceList({pageNum: 1, pageSize: 9999}).then((res) => {
        this.serviceList = res.rows;
      }).catch((e) => {
        this.$message.error(e.toString());
      });
    },
    getRole() {
      getRole(this.roleId).then(response => {
        response.data.roleSort = Number(response.data.roleSort);
        response.data.menuIds = response.data.menuIds || [];
        response.data.serviceIds = response.data.serviceIds || [];
        this.formData = response.data;
        selectServiceListByRoleId(this.roleId).then(response => {
          this.formData.serviceIds = response.data;
          this.getRoleMenuTreeselect();
        }).catch((e) => {
          this.$message.error(e.toString());
        });
      }).catch((e) => {
        this.$message.error(e.toString());
      });
    },
    // selectServiceListByRoleId(){
    //   selectServiceListByRoleId(this.roleId).then(response => {
    //     this.formData.serviceIds = response.data;
    //   }).catch((e) => {
    //     this.$message.error(e.toString());
    //   });
    // },
    getRoleMenuTreeselect() {
      roleMenuTreeselect(this.roleId).then(response => {
        this.serviceMenuCheck(response.checkedKeys);
        // this.formData.menuIds = response.checkedKeys;
      }).catch((e) => {
        this.$message.error(e.toString());
      });
    },
    onSubmit() {
      this.$refs.form.validate().then((validateResult) => {
        if (validateResult === true) {
          this.loading = true;
          if (this.roleId !== 0) {
            this.formData.menuIds = this.getMenuAllCheckedKeys();
            updateRole(this.formData).then((response) => {
              this.$message.success("修改成功");
              this.$emit("reload");
              this.$emit("update:visible", false);
              this.loading = false;
            }).catch((e) => {
              this.loading = false;
              this.$message.error(e.toString());
            });
          } else {
            this.formData.menuIds = this.getMenuAllCheckedKeys();
            addRole(this.formData).then((response) => {
              this.$message.success("新增成功");
              this.$emit("reload");
              this.$emit("update:visible", false);
              this.loading = false;
            }).catch((e) => {
              this.loading = false;
              this.$message.error(e.toString());
            });
          }
        }
      });
    },
    closeDialog() {
      this.$emit("update:visible", false);
    },
    // 所有菜单节点数据
    getMenuAllCheckedKeys() {
      const {tree} = this.$refs;
      const treeItems = tree.getItems();
      // 目前被选中的菜单节点
      const checkedKeys = []
      // 半选中的菜单节点
      const halfCheckedKeys = []
      treeItems.forEach((node) => {
        if (node.checked) {
          checkedKeys.push(node.value)
        }
        if (node.indeterminate) {
          halfCheckedKeys.push(node.value)
        }
      });
      return checkedKeys.concat(halfCheckedKeys);
    },
    // 树权限（展开/折叠）
    handleCheckedTreeExpand() {
      const {menuExpand} = this;
      const {tree} = this.$refs;
      const treeItems = tree.getItems();
      treeItems.forEach((node) => {
        tree.setItem(node.value, {
          expanded: menuExpand,
        });
      });
    },
    // 设置树的值
    setCheckedData(menuIds) {
      const {tree} = this.$refs;
      const treeItems = tree.getItems();
      // tree.store.refreshNodes();
      menuIds.forEach((val) => {
        this.$nextTick(() => {
          // 获取子节点排除自己
          const nodes = tree.getItems(val).filter(v => v.data.id !== val);
          // 1. 没有子节点则选中 2. 子节点是否全部包含在menuIds
          if (nodes.length > 0) {
            const isAllCheck = nodes.every((v, index) => menuIds.includes(v.data.id))
            if (isAllCheck) {
              tree.setItem(val, {
                checked: true
              });
            }
          } else {
            tree.setItem(val, {
              checked: true
            });
          }
        });
      })

    },
    // 树权限（全选/全不选）
    handleCheckedTreeNodeAll(val) {
      const {tree} = this.$refs;
      const treeItems = tree.getItems();
      treeItems.forEach((node) => {
        tree.setItem(node.value, {
          checked: val,
        });
      });
    },

  }
}
</script>

<style lang="less" scoped>
.servicebox {
  border: 1px solid #e5e6e7;
  padding: 5px;
  padding-left: 25px;
  border-radius: 4px;
  display: flex;
  flex-direction: column;
  width: 390px;
}

.menubox {
  display: flex;
  flex-direction: column;
}

.tree-border {
  margin-top: 5px;
  border: 1px solid #e5e6e7;
  background: #FFFFFF none;
  border-radius: 4px;
  width: 390px;
}
</style>
